#ifndef __COMMON_H
#define __COMMON_H

#include <stdio.h>
#include <arpa/inet.h>

#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_malloc.h>
#include <rte_timer.h>
#include <rte_arp.h>


#include <pthread.h>

#define ENABLE_EPOLL                    0 
#define ENABLE_KNI                      0

#if ENABLE_KNI
#include <rte_kni.h>
#endif

#define ARP_STATUS_REQUEST              0
#define ARP_STATUS_REPLAY               1
#define G_PORT                          8888
#define NUM_MBUFS                       (8192-1)
#define RING_SIZE                       1024
#define BURST_SIZE                      32
#define TIMER_RESOLUTION_CYCLES         120000000000ULL // 10ms * 1000 = 10s * 6
#define UDP_APP_RECV_BUFFER_SIZE	    128
#define TCP_APP_RECV_BUFFER_SIZE	    1024
#define TCP_OPTION_LENGTH	            10
#define DEFAULT_FD_NUM	                3
#define MAX_FD_COUNT	                1024
#define TCP_MAX_SEQ		                4294967295      // max 32bit -1
#define TCP_INITIAL_WINDOW              14600           // tcp window
#define MAKE_IPV4_ADDRESS(a,b,c,d)      (a + (b << 8) + (c << 16) + (d << 24))

extern struct rte_mempool * g_mpool;
// int gDpdkPortId = 0;   // 逻辑数值，绑定网口第一个就是0，

extern uint32_t g_src_ip;
extern uint32_t g_dst_ip;
extern uint8_t g_src_mac[RTE_ETHER_ADDR_LEN];
extern uint8_t g_dst_mac[RTE_ETHER_ADDR_LEN];
extern uint16_t g_src_port;
extern uint16_t g_dst_port;
extern uint32_t g_local_ip;
extern unsigned char fd_table[MAX_FD_COUNT];   // bitmap 个数为 MAX_FD_COUNT * 8
extern struct inout_ring * rInstance;
extern struct local_host * g_hosts;
extern struct tcp_table * tcpInstance;
extern const struct rte_eth_conf port_conf_default;  // 最大的rx包
extern uint8_t g_default_arp_mac[RTE_ETHER_ADDR_LEN];
extern struct arp_table_s * arp_table;
extern struct rte_kni * global_kni;


extern uint8_t * get_dst_mac_address(uint32_t dip);


/*********************************结构体***********************************************/
struct inout_ring{
    struct rte_ring * in;
    struct rte_ring * out;
};

struct local_host{        // 定义fd
    int fd;
    uint32_t local_ip;
    uint16_t local_port;
    uint8_t local_mac[RTE_ETHER_ADDR_LEN];
    uint8_t protocol;

    struct rte_ring * send_buf;
    struct rte_ring * recv_buf;

    struct local_host * prev;
    struct local_host * next;

    pthread_cond_t cond;
    pthread_mutex_t mtx;
};

typedef enum TCP_STATUS{
    TCP_STATUS_CLOSED,
    TCP_STATUS_LISTEN,
    TCP_STATUS_SYN_SENT,
    TCP_STATUS_SYN_RCVD,
    TCP_STATUS_ESTABLISHED,
    TCP_STATUS_FIN_WAIT_1,
    TCP_STATUS_FIN_WAIT_2,
    TCP_STATUS_CLOSE_WAIT,
    TCP_STATUS_CLOSING,
    TCP_STATUS_LAST_ACK,
    TCP_STATUS_TIME_WAIT
} TCP_STATUS;


struct tcp_stream{  // 跟 tcp 连接有关的， 五元组  tcb
    /*************定义fd******  local_host  ********/
    int fd;
    // 五元组
    uint32_t d_ip;
    uint16_t d_port;
    uint8_t local_mac[RTE_ETHER_ADDR_LEN];
    uint8_t protocol;

    uint32_t s_ip;
    uint16_t s_port;


    uint32_t seq_num;
    uint32_t ack_num;

    TCP_STATUS status;

    struct rte_ring * send_buf;
    struct rte_ring * rcv_buf;

    struct tcp_stream * prev;
    struct tcp_stream * next;

    pthread_mutex_t  mtx;
    pthread_cond_t cond;
};

struct tcp_table{  // 存储 stream list
    int count;

#if ENABLE_EPOLL
    struct eventpoll * ep;   // 单个epoll， 如果多个server或epoll那么就需要使用 set
#endif

    
    struct tcp_stream * links;
};

struct tcp_fragment{   // tcp 数据包

    //  tcp 头  20字节
    uint16_t s_port;
    uint16_t d_port;
    uint32_t seq_num;  // 本端 当前发数据包 id
    uint32_t ack_num;  // 对端
    uint8_t hdrlen_off;  // 数据起始处距离TCP报文段的起始处有多远【TCP报文段的首部长度】4为最大表示60字节
    uint8_t tcp_flags;
    uint16_t windows;
    uint16_t cksum;
    uint16_t tcp_urp;

    int optlen;
    uint32_t  option[TCP_OPTION_LENGTH];
    unsigned char * data;
    uint32_t length;
};

struct udp_pkg {
    uint32_t d_ip;
    uint32_t s_ip;

    uint16_t d_port;
    uint16_t s_port;

    int protocol;

    uint16_t length;
    unsigned char * data;
};

struct arp_entry_s{
    uint32_t ip;
    uint8_t hwaddr[RTE_ETHER_ADDR_LEN];
    uint8_t type;
    struct arp_entry_s * next;
    struct arp_entry_s * prev;
};

struct arp_table_s{
    struct arp_entry_s *entries;
    int count;
};


/********************************************************************************/
static inline struct inout_ring * ring_instance(void){
    if(rInstance == NULL){
        rInstance = rte_malloc("in_out_ring", sizeof(struct inout_ring), 0);
        memset(rInstance, 0, sizeof(struct inout_ring));
    }
    return rInstance;
}

static inline struct arp_table_s * arp_table_instance(void){
    if(arp_table == NULL){
        arp_table = rte_malloc("arp_table", sizeof(struct arp_table_s), 0);
        if(arp_table == NULL){
            rte_exit(EXIT_FAILURE, "malloc arp_table failed \n");
        }
        memset(arp_table, 0, sizeof (struct arp_table_s));
    }
    return arp_table;
}

static inline struct tcp_table * get_tcp_instance(void){
    if(tcpInstance == NULL){
        tcpInstance = rte_malloc("tcp instance", sizeof(struct tcp_table), 0);
        memset(tcpInstance, 0, sizeof(struct tcp_table));
    }
    return tcpInstance;
}

#endif